// Copyright (C) 1953-2022 NUDT
// Verilog module name - port_state_control 
// Version: V4.0.20220524
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         Network receive interface
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/100ps

module port_state_control
(
        i_clk,
        i_rst_n,
        
        i_data_wr,
        iv_data,

        iv_addr,                          
        iv_wdata,                         
        i_wr_psc,          
        i_rd_psc,                               
        
        o_wr_psc,          
        ov_addr_psc,       
        ov_rdata_psc, 

        i_rc_rxenable    ,
        i_st_rxenable    ,
        i_hardware_initial_finish,      

        ov_data,
        o_data_wr,
        
        ov_eth_type,        
		ov_pkt_priority
);

// I/O
// clk & rst
input                   i_clk;
input                   i_rst_n;
//data input
input                   i_data_wr;
input       [8:0]       iv_data;

input       [18:0]      iv_addr;                         
input       [31:0]      iv_wdata;                        
input                   i_wr_psc;         
input                   i_rd_psc;         

output                  o_wr_psc;          
output     [18:0]       ov_addr_psc;       
output     [31:0]       ov_rdata_psc;
//configuration
input                   i_rc_rxenable    ;
input                   i_st_rxenable    ;
input                   i_hardware_initial_finish; 
//user data output
output     [8:0]        ov_data;
output                  o_data_wr;
output     [15:0]       ov_eth_type;
output     [2:0]        ov_pkt_priority;
// internal wire
wire       [8:0]        wv_data_htd2fts;
wire                    w_data_wr_htd2fts;

wire       [31:0]       wv_pkt_cnt_fts2cpe;
/*
head_and_tail_distinguish_tss head_and_tail_distinguish_tss_inst(
.i_clk          (i_clk),
.i_rst_n        (i_rst_n),
.i_data_wr      (i_data_wr),
.iv_data        (iv_data),
.ov_data        (wv_data_htd2fts),
.o_data_wr      (w_data_wr_htd2fts)
);
*/
frame_transmittion_select frame_transmittion_select_inst(
.i_clk          (i_clk),
.i_rst_n        (i_rst_n),

.i_rc_rxenable  (i_rc_rxenable    ),
.i_st_rxenable  (i_st_rxenable    ),
.i_hardware_initial_finish(i_hardware_initial_finish),
//.i_port_mode    (1'b0),

.iv_data        (iv_data  ),//(wv_data_htd2fts),
.i_data_wr      (i_data_wr),//(w_data_wr_htd2fts),

.ov_data        (ov_data),
.o_data_wr      (o_data_wr),
.ov_pkt_priority(ov_pkt_priority),
.ov_eth_type    (ov_eth_type),
.ov_pkt_cnt     (wv_pkt_cnt_fts2cpe)
);
command_parse_and_encapsulate_psc command_parse_and_encapsulate_psc_inst(
.i_clk          (i_clk),
.i_rst_n        (i_rst_n),

.iv_addr        (iv_addr),                         
.iv_wdata       (iv_wdata),                        
.i_wr_psc       (i_wr_psc),         
.i_rd_psc       (i_rd_psc),         

.o_wr_psc       (o_wr_psc),         
.ov_addr_psc    (ov_addr_psc),      
.ov_rdata_psc   (ov_rdata_psc),

.iv_pkt_cnt_fts2cpe(wv_pkt_cnt_fts2cpe)
);

reg [1:0]       pktin_cnt_state;
reg [31:0]      rv_ind_cnt/*synthesis noprune*/;    
localparam  idle1_s      = 2'b00,
            tran1_s      = 2'b10;            
always@(posedge i_clk or negedge i_rst_n)
    if(!i_rst_n) begin
        rv_ind_cnt              <= 32'b0 ;  
        pktin_cnt_state       <= idle1_s;   
    end
    else begin
        case(pktin_cnt_state)
            idle1_s:begin        
                if(i_data_wr == 1'b1) begin//head
                    if(iv_data == 8'h6c)begin
                        rv_ind_cnt          <= rv_ind_cnt + 1'b1 ;
                    end
                    else begin
                        rv_ind_cnt          <= rv_ind_cnt;                 
                    end
                    pktin_cnt_state       <= tran1_s;  
                end
                else begin  //invalid
                    pktin_cnt_state   <= idle1_s;
                end
            end

            tran1_s:begin
                if(i_data_wr == 1'b0)begin//middle
                    pktin_cnt_state   <= idle1_s;                   
                end
                else begin
                    pktin_cnt_state         <= tran1_s;
                end
            end
            default:begin
                pktin_cnt_state       <= idle1_s;
            end
        endcase
    end
	
reg [1:0]       pktout_cnt_state;
reg [31:0]      rv_outd_cnt/*synthesis noprune*/;    
localparam  idle2_s      = 2'b00,
            tran2_s      = 2'b10;            
always@(posedge i_clk or negedge i_rst_n)
    if(!i_rst_n) begin
        rv_outd_cnt              <= 32'b0 ;  
        pktout_cnt_state       <= idle2_s;   
    end
    else begin
        case(pktout_cnt_state)
            idle2_s:begin        
                if(o_data_wr == 1'b1) begin//head
                    if(ov_data == 9'h16c)begin
                        rv_outd_cnt          <= rv_outd_cnt + 1'b1 ;
                    end
                    else begin
                        rv_outd_cnt          <= rv_outd_cnt;                 
                    end
                    pktout_cnt_state       <= tran2_s;  
                end
                else begin  //invalid
                    pktout_cnt_state   <= idle2_s;
                end
            end

            tran2_s:begin
                if(o_data_wr == 1'b0)begin//middle
                    pktout_cnt_state   <= idle2_s;                   
                end
                else begin
                    pktout_cnt_state         <= tran2_s;
                end
            end
            default:begin
                pktout_cnt_state       <= idle2_s;
            end
        endcase
    end	

endmodule